#include "chrono.h"
#include <array>
#include <cinttypes>
#include <cstring>



bool Utility::is_valid(timepoint t) {
    return timepoint{} < t;
}

Utility::timepoint Utility::now() {
    return clock::now();
}

Utility::ClockCntType Utility::count(duration td) {
    return td.count();
}

Utility::ClockCntType Utility::epoch_count(timepoint t) {
    return t.time_since_epoch().count();
}

std::string Utility::to_string(timepoint t) {
    std::array<char, 1 << 6> buffer{};
    ::snprintf(buffer.data(), buffer.size() - 1, "%" PRId64 ".%09" PRId64 "", 
               epoch_count(t) / COUNT_PER_SEC, epoch_count(t) % COUNT_PER_SEC);
    return buffer.data();
}

std::string Utility::to_formatted_string(timepoint t) {
    constexpr auto START_YEAR = 1900;
    std::array<char, 1 << 6> buffer{};
    const auto s = clock::to_time_t(t);
    struct tm tt{};
    ::localtime_r(&s, &tt);
    ::snprintf(
        buffer.data(), buffer.size(), "%4d/%02d/%02d %02d:%02d:%02d.%09" PRId64,
        tt.tm_year + START_YEAR, tt.tm_mon, tt.tm_mday,
        tt.tm_hour, tt.tm_min, tt.tm_sec, epoch_count(t) % COUNT_PER_SEC
    );
    return buffer.data();
}

double Utility::cast_second(duration td) {
    return static_cast<double>(count(td)) / COUNT_PER_SEC;
}

Utility::duration Utility::cast_duration(double sec) {
    return duration{static_cast<ClockCntType>(sec * COUNT_PER_SEC)};
}
